package com.pic.others.service.impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pic.common.utils.R;
import com.pic.others.config.xfxh.XfXhConfig;
import com.pic.others.config.xfxh.XfXhStreamClient;
import com.pic.others.domain.dto.xfxh.MsgDTO;
import com.pic.others.domain.po.Picture;
import com.pic.others.domain.po.PictureDescribe;
import com.pic.others.mapper.PictureDescribeMapper;
import com.pic.others.mq.XfXhWebSocketListener;
import com.pic.others.service.IPictureDescribeService;
import com.pic.others.service.IPictureService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.WebSocket;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.UUID;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author koshi
 * @since 2023-11-24
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class PictureDescribeServiceImpl extends ServiceImpl<PictureDescribeMapper, PictureDescribe> implements IPictureDescribeService {

    private final XfXhStreamClient xfXhStreamClient;
    private final IPictureService pictureService;



    private final XfXhConfig xfXhConfig;

    @Override
    public R<PictureDescribe> chatBydescribe(Long pictureId) {
        log.info("pictureId:{}",pictureId);
        PictureDescribe pictureDescribe =lambdaQuery().eq(PictureDescribe::getPicId, pictureId).one();
        if(pictureDescribe==null){
            return R.error("还未分类，无法生成文案");
        }



        if(pictureDescribe!=null&&pictureDescribe.getLetters()!=null){
            return R.success(pictureDescribe);
        }

      String question;
        if(pictureDescribe.getDescription()!=null){
            question="生成一句关于"+ pictureDescribe.getDescription() +"情绪文案要求用名人名言，" +
                    "要求不要出现名人名字，要求信达雅";
        }else{
            question="生成一句关于"+ pictureDescribe.getThing() +"物品文案要求用名人名言，" +
                    "要求不要出现名人名字，要求信达雅";
        }

        Picture picture = pictureService.getById(pictureId);
        pictureDescribe.setSize(picture.getSize());
        if(picture==null) {
            return R.error("未知错误请联系管理员");
        }
        log.info(question);
        // 如果是无效字符串，则不对大模型进行请求
        if (StrUtil.isBlank(question)) {
            log.info("无效问题，请重新输入");
            return R.error( "无效描述，请重新输入");
        }
        // 获取连接令牌
        if (!xfXhStreamClient.operateToken(XfXhStreamClient.GET_TOKEN_STATUS)) {
            log.info("当前大模型连接数过多，请稍后再试");
            return R.error("连接超时，请稍后再试");
        }

        // 创建消息对象
        MsgDTO msgDTO = MsgDTO.createUserMsg(question);
        // 创建监听器
        XfXhWebSocketListener listener = new XfXhWebSocketListener();
        // 发送问题给大模型，生成 websocket 连接
        WebSocket webSocket = xfXhStreamClient.sendMsg(UUID.randomUUID().toString().substring(0, 10), Collections.singletonList(msgDTO), listener);
        if (webSocket == null) {
            // 归还令牌
            xfXhStreamClient.operateToken(XfXhStreamClient.BACK_TOKEN_STATUS);
            return R.error("系统内部错误，请联系管理员");
        }
        try {
            int count = 0;
            // 为了避免死循环，设置循环次数来定义超时时长
            int maxCount = xfXhConfig.getMaxResponseTime() * 5;
            while (count <= maxCount) {
                Thread.sleep(200);
                if (listener.isWsCloseFlag()) {
                    break;
                }
                count++;
            }
            if (count > maxCount) {
                return R.error("响应超时，请联系管理员");
            }
            // 响应大模型的答案
            log.info("listener.getAnswer().toString();" + listener.getAnswer().toString());
//            return R.success( String.valueOf(listener.getAnswer()));

            pictureDescribe.setLetters(String.valueOf(listener.getAnswer()));
            updateById(pictureDescribe);
            return R.success(pictureDescribe);
        } catch (InterruptedException e) {
            log.error("错误：" + e.getMessage());
            return R.error("系统内部错误，请联系管理员");
        } finally {
            // 关闭 websocket 连接
            webSocket.close(1000, "");
            // 归还令牌
            xfXhStreamClient.operateToken(XfXhStreamClient.BACK_TOKEN_STATUS);
        }

    }

    @Override
    public R<String> getDescribe(Long pictureId) {
        PictureDescribe one = lambdaQuery().eq(PictureDescribe::getPicId, pictureId).one();
        String describe=one.getDescription();
        return R.success(describe);
    }
}
